package common;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;


import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.*;
import java.util.Map;


/**
 * Created by xiaoban on 2019/5/9.
 * httpclient封装类
 */
public class ClientUtils {


    /**
     * POST             请求
     *
     * @param url    请求地址
     * @param params 请求参数
     * @param encode 编码格式
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String doPostMethod(String url, String params, String encode) throws ClientProtocolException, IOException {
        HttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);

        httpPost.addHeader("Content-Type", "application/soap+xml;charset=UTF-8");
        //httpPost.setHeader("token", token);
        HttpEntity entity = new StringEntity(params, encode);
        httpPost.setEntity(entity);

        HttpResponse response = httpclient.execute(httpPost);
        String result = EntityUtils.toString(response.getEntity(), "utf-8");
        return result;
    }

    /**
     * GET
     *
     * @param url
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String doGetMethod(String url) throws ClientProtocolException, IOException {
        HttpClient httpclient = HttpClients.createDefault();

        // 创建httpget.
        HttpGet httpget = new HttpGet(url);
        //System.out.println("executing request " + httpget.getURI());
        HttpResponse response = httpclient.execute(httpget);
        String result = EntityUtils.toString(response.getEntity());
        return result;
    }

    /**
     * 上传文件
     *
     * @param graphurl    接口地址
     * @param inputStream 文件二进制
     * @return
     */
    public static String uploadFile(String graphurl, InputStream inputStream) {
        String line = null;//接口返回的结果
        try {
            // 换行符
            final String newLine = "\r\n";
            final String boundaryPrefix = "--";
            // 定义数据分隔线
            String BOUNDARY = "========7d4a6d158c9";
            // 服务器的域名
            URL url = new URL(graphurl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置为POST情
            conn.setRequestMethod("POST");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求头参数
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Charsert", "UTF-8");
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
            conn.setRequestProperty("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1");
            OutputStream out = new DataOutputStream(conn.getOutputStream());
            // 上传文件
            StringBuilder sb = new StringBuilder();
            sb.append(boundaryPrefix);
            sb.append(BOUNDARY);
            sb.append(newLine);
            // 文件参数,photo参数名可以随意修改
            sb.append("Content-Disposition: form-data;name=\"image\";filename=\""
                    + "https://api.weixin.qq.com" + "\"" + newLine);
            sb.append("Content-Type:application/octet-stream");
            // 参数头设置完以后需要两个换行，然后才是参数内容
            sb.append(newLine);
            sb.append(newLine);
            // 将参数头的数据写入到输出流中
            out.write(sb.toString().getBytes());
            // 读取文件数据
            byte[] bytes = new byte[1024 * 8];
            while (inputStream.read(bytes) != -1) {
                out.write(bytes);
            }
            // 最后添加换行
            out.write(newLine.getBytes());
            // 定义最后数据分隔线，即--加上BOUNDARY再加上--。
            byte[] end_data = (newLine + boundaryPrefix + BOUNDARY
                    + boundaryPrefix + newLine).getBytes();
            // 写上结尾标识
            out.write(end_data);
            out.flush();
            out.close();
            // 定义BufferedReader输入流来读取URL的响应
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            while ((line = reader.readLine()) != null) {
                return line;
            }
        } catch (Exception e) {
            System.out.println("发送POST请求出现异常！" + e);
        }
        return line;
    }


    /**
     * 微信图片恶意的过滤
     *
     * @param inputStream
     * @param accessToken
     * @return
     */
    public static Boolean checkPic(String url, InputStream inputStream, String accessToken) {
        try {
            CloseableHttpClient httpclient = HttpClients.createDefault();
            CloseableHttpResponse response = null;
            HttpPost request = new HttpPost("https://api.weixin.qq.com/wxa/img_sec_check?access_token=" + accessToken);
            request.addHeader("Content-Type", "application/octet-stream");
            byte[] byt = new byte[inputStream.available()];
            inputStream.read(byt);
            request.setEntity(new ByteArrayEntity(byt, ContentType.create("image/jpg")));
            response = httpclient.execute(request);
            HttpEntity httpEntity = response.getEntity();
            String result = EntityUtils.toString(httpEntity, "UTF-8");// 转成string
            JSONObject jso = JSONObject.parseObject(result);
            System.out.println(jso + "-------------验证效果");
            Object errcode = jso.get("errcode");
            int errCode = (int) errcode;
            if (errCode == 0) {
                return true;
            } else if (errCode == 87014) {
                System.out.println("图片内容违规-----------");
                return false;
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("----------------调用腾讯内容过滤系统出错------------------");
            return true;
        }
    }

    /**
     * 使用证书发送post请求
     *
     * @param url
     * @param data
     * @param mch_id
     * @param certStream
     * @return
     * @throws Exception
     */
    public static Map<String, String> certPost(String url, String data, String mch_id, InputStream certStream) throws Exception {
        HttpPost httpPost = new HttpPost(url);
        // 得指明使用UTF-8编码，否则到API服务器XML的中文不能被成功识别
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.setEntity(new StringEntity(data, "UTF-8"));
        // 加载含有证书的http请求
        HttpResponse response = HttpClients.custom().setSSLSocketFactory(initCert(mch_id, certStream)).build().execute(httpPost);
        String result = EntityUtils.toString(response.getEntity(), "utf-8");
        Map<String, String> map = WXPayUtils.xmlToMap(result);
        return map;
    }

    /**
     * 使用证书上传文件
     *
     * @param mch_id
     * @param certStream
     * @param url
     * @param multipartEntityBuilder
     * @return
     * @throws Exception
     */
    public static Map<String, String> certUploadFile(String mch_id, InputStream certStream, String url, MultipartEntityBuilder multipartEntityBuilder) throws Exception {
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(initCert(mch_id, certStream)).build();
        try {
            // 请求微信图片上传接口
            HttpPost httpPost = new HttpPost(url);
            RequestConfig config = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(10000).setSocketTimeout(10000).build();
            httpPost.setConfig(config);
            httpPost.addHeader(HTTP.CONTENT_TYPE, "multipart/form-data; charset=UTF-8");
            httpPost.addHeader(HTTP.USER_AGENT, "wxpay sdk java v1.0 " + mch_id);
            httpPost.setEntity(multipartEntityBuilder.build());
            CloseableHttpResponse response = httpclient.execute(httpPost);
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            Map<String, String> resultMap = WXPayUtils.xmlToMap(result);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 获取证书信息
     *
     * @param mch_id
     * @param certStream
     * @return
     * @throws Exception
     */
    public static SSLConnectionSocketFactory initCert(String mch_id, InputStream certStream) throws Exception {
        // 证书
        char[] password = mch_id.toCharArray();
//        InputStream certStream = config.getCertStream();
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(certStream, password);

        // 实例化密钥库 & 初始化密钥工厂
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, password);

        // 创建 SSLContext
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());

        //创建请求
        return new SSLConnectionSocketFactory(
                sslContext,
                new String[]{"TLSv1","TLSv1.1","TLSv1.2"},
                null,
                new DefaultHostnameVerifier());
    }


}
